package com.yubest.springboothello.interceptors;

import lombok.Getter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 统计接口调用次数
 *
 * @Author: hweiyu
 * @Date: 2023/6/2 11:11
 */
@Component
@Getter
public class RequestStatInterceptor implements HandlerInterceptor {

    private final Map<String, Long> counter = new ConcurrentHashMap<>();

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //获取模板uri。针对uri中包含@PathVariable注解的参数时，例如原接口定义为：/say/{msg}，实际请求uri为：/say/hello，此时获取到的uri为：/say/{msg}
        String uriKey = this.getUriKey(request);
        counter.compute(uriKey, (key, value) -> value == null ? 1 : value + 1);
        return true;
    }

    public void init(List<String> uriList) {
        for (String uri : uriList) {
            counter.put(uri, 0L);
        }
    }

    private String getUriKey(HttpServletRequest request) {
        String uri = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
        String method = request.getMethod();
        return String.format("{%s %s}", method, uri);
    }

    @Component
    public static class RequestStatInitRunner implements ApplicationRunner {

        @Autowired
        private RequestMappingHandlerMapping requestMappingHandlerMapping;

        @Autowired
        private RequestStatInterceptor requestStatInterceptor;

        @Override
        public void run(ApplicationArguments args) throws Exception {
            Map<RequestMappingInfo, HandlerMethod> map = requestMappingHandlerMapping.getHandlerMethods();
            List<String> uriList = new ArrayList<>();
            for (RequestMappingInfo requestMappingInfo : map.keySet()) {
                uriList.add(requestMappingInfo.toString());
            }
            requestStatInterceptor.init(uriList);
        }
    }
}
